package generation;

import java.util.ArrayList;

public class PasswordMemorisation {
	//return a value between 0 and 1, which correspond to the memorization fitness pour the individual indivString
	// the ArrayList contains the evaluatedIndividual that are liked by the user.
	public static float passwordMemorisation(String indivString, ArrayList<String> evaluatedIndiv) {
		//we store all the distance from indivString to the evaluatedIndiv
		ArrayList<Double> temp_inv_dist = new ArrayList<Double>();
		for(int i = 0; i < evaluatedIndiv.size(); i++) {
			double temp_dist = levenshteinDistance(indivString, evaluatedIndiv.get(i));
			//if identical, return 1.
			if(temp_dist  == 0) {
				return 1;
			}
			//if not, we store the weight, witch is equal to the invers of the distance
			else {
				temp_inv_dist.add(1/temp_dist);
			}
		}
		//we calculated the sum of the weight
		double weight_sum = 0;
		for(int i = 0; i < evaluatedIndiv.size(); i++) {
			weight_sum += temp_inv_dist.get(i);
		}
		// then we evaluated the inverse distance weigthing formula.
		float ponderate_weight_sum = 0;
		for(int i = 0; i < evaluatedIndiv.size(); i++) {
			float temp_fit = (float) (1/(1+temp_inv_dist.get(i)/3));
			ponderate_weight_sum += temp_inv_dist.get(i) * temp_fit / weight_sum;
		}

		return ponderate_weight_sum;
	}

	/**
	 * compute the Levenshtein distance between two strings
	 * @author Xavier Philippeau
	 * 
	 * @param s0 String 0
	 * @param s1 String 1
	 * @return the Levenshtein distance
	 */
	private static double levenshteinDistance(String s0, String s1) {
		int len0 = s0.length()+1;
		int len1 = s1.length()+1;

		// the array of distances
		int[] cost = new int[len0];
		int[] newcost = new int[len0];

		// initial cost of skipping prefix in String s0
		for(int i=0;i<len0;i++) cost[i]=i;

		// dynamicaly computing the array of distances

		// transformation cost for each letter in s1
		for(int j=1;j<len1;j++) {

			// initial cost of skipping prefix in String s1
			newcost[0]=j-1;

			// transformation cost for each letter in s0
			for(int i=1;i<len0;i++) {

				// matching current letters in both strings
				int match = (s0.charAt(i-1)==s1.charAt(j-1))?0:1;

				// computing cost for each transformation
				int cost_replace = cost[i-1]+match;
				int cost_insert  = cost[i]+1;
				int cost_delete  = newcost[i-1]+1;

				// keep minimum cost
				newcost[i] = min(cost_insert, cost_delete, cost_replace);
			}

			// swap cost/newcost arrays
			int[] swap=cost; cost=newcost; newcost=swap;
		}

		// the distance is the cost for transforming all letters in both strings
		return cost[len0-1];
	}

	//return the minumum between the three given integer.
	private static int min(int cost_insert, int cost_delete, int cost_replace) {
		int tempMin = cost_insert;
		if(tempMin > cost_delete)
			tempMin = cost_delete;
		if(tempMin > cost_replace)
			tempMin = cost_replace;
		return tempMin;
	}
}
